﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Resources;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Printing;
using System.Windows.Resources;
using System.Windows.Shapes;

namespace SmartSpace.Silverlight
{
    public partial class SlEditor : UserControl
    {
        private bool m_isReadOnly;

        public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(string), typeof(SlEditor), null); 

        public string Content
        {
            get
            {
                //return (string)GetValue(ContentProperty);
                return rtb.Xaml;
            }
            set
            {
                if (value.StartsWith("<Section"))
                {
                    SetValue(ContentProperty, value); 
                    rtb.Xaml = value;
                }
                else
                {
                    SetValue(ContentProperty, value); 
                    rtb.Selection.Text = value;
                }
            }
        }

        public bool IsReadOnly
        {
            get
            {
                return m_isReadOnly;
            }
            set
            {
                m_isReadOnly = value;
                if (m_isReadOnly)
                {
                    rtb.IsTabStop = false;
                    rtb.TextWrapping = TextWrapping.Wrap;
                    m_stackPanelToolbar.Visibility = System.Windows.Visibility.Collapsed;
                    rtb.IsReadOnly = m_isReadOnly;
                }
                else
                {
                    rtb.IsTabStop = true;
                    rtb.TextWrapping = TextWrapping.Wrap;
                    m_stackPanelToolbar.Visibility = System.Windows.Visibility.Visible;
                    rtb.IsReadOnly = m_isReadOnly;
                }
            }
        }

        public SlEditor()
        {
            InitializeComponent();
            Loaded += new RoutedEventHandler(MainPage_Loaded);
        }

        //Initialize the RichTextBox. The intial text is saved as XAML inthe Hamlet.docx file.
        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
           //rtb.Xaml = XElement.Load("/SilverlightTextEditor;component/sample.sav").ToString();
        }

        #region Bold, Italics & Underline

        //Set Bold formatting to the selected content 
        private void btnBold_Click(object sender, RoutedEventArgs e)
        {
            if (rtb != null && rtb.Selection.Text.Length > 0)
            {
                if (rtb.Selection.GetPropertyValue(Run.FontWeightProperty) is FontWeight && ((FontWeight)rtb.Selection.GetPropertyValue(Run.FontWeightProperty)) == FontWeights.Normal)
                    rtb.Selection.ApplyPropertyValue(Run.FontWeightProperty, FontWeights.Bold);
                else
                    rtb.Selection.ApplyPropertyValue(Run.FontWeightProperty, FontWeights.Normal);
            }
            ReturnFocus();
        }

        //Set Italic formatting to the selected content 
        private void btnItalic_Click(object sender, RoutedEventArgs e)
        {
            if (rtb != null && rtb.Selection.Text.Length > 0)
            {
                if (rtb.Selection.GetPropertyValue(Run.FontStyleProperty) is FontStyle && ((FontStyle)rtb.Selection.GetPropertyValue(Run.FontStyleProperty)) == FontStyles.Normal)
                    rtb.Selection.ApplyPropertyValue(Run.FontStyleProperty, FontStyles.Italic);
                else
                    rtb.Selection.ApplyPropertyValue(Run.FontStyleProperty, FontStyles.Normal);
            }
            ReturnFocus();
        }

        //Set Underline formatting to the selected content 
        private void btnUnderline_Click(object sender, RoutedEventArgs e)
        {
            if (rtb != null && rtb.Selection.Text.Length > 0)
            {
                if (rtb.Selection.GetPropertyValue(Run.TextDecorationsProperty) == null)
                    rtb.Selection.ApplyPropertyValue(Run.TextDecorationsProperty, TextDecorations.Underline);
                else
                    rtb.Selection.ApplyPropertyValue(Run.TextDecorationsProperty, null);
            }
            ReturnFocus();

        }
        #endregion 

        #region Font Type, Color & size 

        //Set font type to selected content
        private void cmbFonts_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (rtb != null && rtb.Selection.Text.Length > 0)
            {
                rtb.Selection.ApplyPropertyValue(Run.FontFamilyProperty, new FontFamily((cmbFonts.SelectedItem as ComboBoxItem).Tag.ToString()));
            }
            ReturnFocus();
        }

        //Set font size to selected content
        private void cmbFontSizes_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (rtb != null && rtb.Selection.Text.Length > 0)
            {
                rtb.Selection.ApplyPropertyValue(Run.FontSizeProperty, double.Parse((cmbFontSizes.SelectedItem as ComboBoxItem).Tag.ToString()));
            }
            ReturnFocus();
        }

        //Set font color to selected content
        private void cmbFontColors_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (rtb != null && rtb.Selection.Text.Length > 0)
            {
                string color = (cmbFontColors.SelectedItem as ComboBoxItem).Tag.ToString();

                SolidColorBrush brush = new SolidColorBrush(Color.FromArgb(
                    byte.Parse(color.Substring(0, 2), System.Globalization.NumberStyles.HexNumber),
                    byte.Parse(color.Substring(2, 2), System.Globalization.NumberStyles.HexNumber),
                    byte.Parse(color.Substring(4, 2), System.Globalization.NumberStyles.HexNumber),
                    byte.Parse(color.Substring(6, 2), System.Globalization.NumberStyles.HexNumber)));

                rtb.Selection.ApplyPropertyValue(Run.ForegroundProperty, brush);
            }
            ReturnFocus();
        }
        #endregion 

        #region Clipboard Operations

        //Cut the selected text
        private void btnCut_Click(object sender, RoutedEventArgs e)
        {
            Clipboard.SetText(rtb.Selection.Text);
            rtb.Selection.Text = "";
            ReturnFocus();
        }

        //Copy the selected text
        private void btnCopy_Click(object sender, RoutedEventArgs e)
        {
            Clipboard.SetText(rtb.Selection.Text);
            ReturnFocus();
        }

        //paste the text
        private void btnPaste_Click(object sender, RoutedEventArgs e)
        {
            rtb.Selection.Text = Clipboard.GetText();
            ReturnFocus();
        }
        #endregion 

        #region Context Menu

        //Though we dont execute any logic on Right Mouse button down, we need to ensure the event is set to be handled to allow
        //the subsequent Right Mouse button up to be raised on the control. The context menu is displayed when the right mouse
        //button up event is raised. 
        private void rtb_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
        }

        private void rtb_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            //Construct and display the context menu

            //RTBContextMenu menu = new RTBContextMenu(rtb);
            //menu.Show(e.GetPosition(LayoutRoot));
        }
        #endregion 

        #region DragAndDrop

        private void rtb_Drop(object sender, System.Windows.DragEventArgs e)
        {
            VisualStateManager.GoToState(this, "Normal", true);

            //the Drop event passes in an array of FileInfo objects for the list of files that were selected and drag-dropped onto the RichTextBox.
            if (e.Data == null)
            {
                ReturnFocus();
                return;
            }

            //This checks if the dropped objects are files and if not, return. 
            IDataObject f = e.Data as IDataObject;

            if (f == null)
            {
                ReturnFocus();
                return;
            }

            object data = f.GetData(DataFormats.FileDrop);
            FileInfo[] files = data as FileInfo[];

            if (files == null)
            {
                ReturnFocus();
                return;
            }

            //Walk through the list of FileInfo objects of the selected and drag-dropped files and parse the .txt and .docx files 
            //and insert their content in the RichTextBox.
            foreach (FileInfo file in files)
            {
                if (file == null)
                {
                    continue;
                }

                if (file.Extension.Equals(".txt"))
                {
                    ParseTextFile(file);
                }
                else if (file.Extension.Equals(".docx"))
                {
                    ParseDocxFile(file);
                }
            }
            ReturnFocus();
        }

        //Create a StreamReader on the text file and read as a string. 
        private void ParseTextFile(FileInfo file)
        {
            Stream sr = file.OpenRead();
            string contents;
            using (StreamReader reader = new StreamReader(sr))
            {
                contents = reader.ReadToEnd();
            }

            rtb.Selection.Text = contents;
            sr.Close();                 
        }

        private void ParseDocxFile(FileInfo file)
        {
            //Stream sr = file.OpenRead();
            //string contents;

            //StreamResourceInfo zipInfo = new StreamResourceInfo(sr, null);
            //StreamResourceInfo wordInfo = Application.GetResourceStream(zipInfo, new Uri("word/document.xml", UriKind.Relative));

            //using (StreamReader reader = new StreamReader(wordInfo.Stream))
            //{
            //    contents = reader.ReadToEnd();
            //}

            //XDocument xmlFile = XDocument.Parse(contents);
            //XNamespace w = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";

            //var query = from xp in xmlFile.Descendants(w + "p")
            //            select xp;
            //Paragraph p = null;
            //Run r = null;
            //foreach (XElement xp in query)
            //{
            //    p = new Paragraph();
            //    var query2 = from xr in xp.Descendants(w + "r")
            //                 select xr;
            //    foreach (XElement xr in query2)
            //    {
            //        r = new Run();
            //        var query3 = from xt in xr.Descendants()
            //                     select xt;
            //        foreach (XElement xt in query3)
            //        {
            //            if (xt.Name == (w + "t"))
            //                r.Text = xt.Value.ToString();
            //            else if (xt.Name == (w + "br"))
            //                p.Inlines.Add(new LineBreak());
            //        }
            //        p.Inlines.Add(r);
            //    }
            //    p.Inlines.Add(new LineBreak());
            //    rtb.Blocks.Add(p);
            //}
        }

        private void rtb_DragEnter(object sender, System.Windows.DragEventArgs e)
        {
            VisualStateManager.GoToState(this, "DragOver", true);
        }

        private void rtb_DragLeave(object sender, System.Windows.DragEventArgs e)
        {
            VisualStateManager.GoToState(this, "Normal", true);        
        }

        #endregion 

        #region helper functions

        private void ReturnFocus()
        {
            if (rtb != null)
                rtb.Focus();
        }
        #endregion 

        private void btnAddHeight_Click(object sender, RoutedEventArgs e)
        {
            if (rtb.Height + 50 > 800)
            {
                rtb.Height = 800;
            }
            else
            {
                rtb.Height = rtb.Height + 50;
            }
        }

        private void btnDecHeight_Click(object sender, RoutedEventArgs e)
        {
            if (rtb.Height - 50 < 200)
            {
                rtb.Height = 200;
            }
            else
            {
                rtb.Height = rtb.Height - 50;
            }
        }
    }
}
